#include "soapH.h"
#include "soapStub.h"
#include "webservice_svr.nsmap"
#define _BULLETIN_PRIVILEGE_
#include "process.h"

system_net_info msgbus_broad1;
char*  recv_buf_ptr=NULL;
struct  app_buf_head ah;
IHdbConnection *m_HdbConn = CreateHdbConnection();

char uName[32],userName[32];
char nodeName[64];
char *listFac = NULL;

int http_get(struct soap *para_soap)
{
    ns__pointValue res;
    char *s = strchr( para_soap->path, '?' );
    if( !s || strcmp( s,"?wsdl")==0 )
    {
        return SOAP_GET_METHOD;
    }

    FILE *fd = NULL;
    string fielPath(para_soap->path);


    int comma_n = fielPath.find( "?" );
    std::string tmp_s1 = "",tmp_s2 = "";
    tmp_s1 = fielPath.substr(0,comma_n);
    tmp_s2 = fielPath.substr(comma_n+1);

    size_t pos = tmp_s1.rfind("/");
    string tag(tmp_s1, pos+1);

    if (strcmp(tag.c_str(),"GetPointValue10m")==0)
    {
        comma_n = tmp_s2.find("&");
        string s1 = tmp_s2.substr(0,comma_n);
        string s11 = tmp_s2.substr(comma_n+1);
        comma_n = s11.find("&");
        string s2 = s11.substr(0,comma_n);
        string s3 = s11.substr(comma_n+1);


        string tmp = "";
        comma_n = s1.find("=");
        tmp = s1.substr(comma_n+1);
        char wtg_id[16]={0};
        memcpy(wtg_id,tmp.c_str(),16);

        comma_n = s2.find("=");
        tmp = s2.substr(comma_n+1);
        char pointname[32]={0};
        memcpy(pointname,tmp.c_str(),32);


        replace(s3,"%20"," ");
        comma_n = s3.find("=");
        tmp = s3.substr(comma_n+1);

        ns__GetPointValue10m(para_soap,MulityByteToWideChar(wtg_id),MulityByteToWideChar(pointname),MulityByteToWideChar(const_cast<char*>(tmp.c_str())),&res);

    }

    int val = 0;
    char buf[256];  
    soap_response(para_soap, SOAP_HTML);
    char * code = WideCharToMulityByte(res.code);
    char * message = WideCharToMulityByte(res.message);
    if (strlen(message)==0)
    {
        if ((res.std+1)==0)
            sprintf(buf, "{\"code\":\"%s\",\"value\":%d,\"std\":%d}", code,(int)res.value,(int)res.std);
        else
            sprintf(buf, "{\"code\":\"%s\",\"value\":%.2f,\"std\":%.2f}", code,res.value,res.std);
    }
    else
        sprintf(buf, "{\"code\":\"%s\",\"message\":\"%s\"}",code,message);

    soap_send(para_soap, buf);  
    soap_end_send(para_soap);  
    delete[] code;
    delete[] message;

    if (res.code!=NULL)
    {
        delete[] res.code;;
        res.code = NULL;
    }
    if (res.message!=NULL)
    {
        delete[] res.message;
        res.message = NULL;
    }
    
    return SOAP_OK;
}



int main(int argc, char* argv[])
{
    SETLOGFILE("webservice_svr");
    int m, s; 
    struct soap para_soap;
    soap_init(&para_soap);
    soap_set_mode(&para_soap, SOAP_C_UTFSTRING );    //设置编码
    para_soap.mode|=SOAP_C_UTFSTRING;

    if(msgbus_broad1.set_system_net_info("webservice_svr", MSGBUS_NO) == FALSE)
    {
        TRACE_ERROR("Exit：msgbus is not running.\n");
        ReleasePromanSem();
        return -1;
    }
    int num=0;
    int ret = msgbus_broad1.count_process_num("webservice_svr",num);
    if ((ret > 0) && (num >1))
    {
        ReleasePromanSem();
        exit(-1);
    }

    InitApp(SCADA);
    InitApp(PUBLIC);
    connect_Oracle();
    //para_soap.fget = http_get;

    m = soap_bind(&para_soap,NULL, 4005, 100); //端口可配
    if (m < 0)
    {
        soap_print_fault(&para_soap, stderr);
        ReleasePromanSem();
        TRACE_FATAL("Exit：soap_bind fail.\n");
        ShutDownApp(SCADA);
        ShutDownApp(PUBLIC);
        exit(-1);
    }

    fprintf(stderr, "Socket connection successful: master socket = %d\n", m);

    ReleasePromanSem();
    for ( int i = 1; ; i++)
    { 
        s = soap_accept(&para_soap); 
        if (s < 0)
        { 
            soap_print_fault(&para_soap, stderr);
            TRACE_FATAL("Exit：soap_accept fail.\n");
            exit(-1);
        }
        fprintf(stderr, "%d: accepted connection from IP=%d.%d.%d.%d socket=%d\n", i,
            (para_soap.ip>>24)&0xFF, (para_soap.ip>>16)&0xFF, (para_soap.ip>>8)&0xFF, para_soap.ip&0xFF, s);
        para_soap.fget = http_get;
        soap_serve(&para_soap);//该句说明该server的服务
        soap_end(&para_soap);


        //收报文
        while(msgbus_broad1.msgbus_receive_message(ah, recv_buf_ptr) >= 0)
        {
            switch (ah.rhead.report_type)
            {
            case MSGBUS_CGN_MODIFY_AC:
                ProcessAcModify(recv_buf_ptr);
                break;
            case MSGBUS_CGN_MODIFY_MC:
                ProcessMcModify(recv_buf_ptr);
                break;
            }
        }
    }

    if (listFac)
    {
        delete[] listFac;
        listFac = NULL;
    }

    ShutDownApp(SCADA);
    ShutDownApp(PUBLIC);

    return 0;
}


//server端的实现函数
int ns__GetUserPriv(struct soap* para_soap, xsd__string userName, xsd__string userPassword,xsd__string facAlias, xsd__string *resUserPriv)
{
    int ret;
    int retNums,loop;
    char *BufPtr=NULL;
    int BufSize;
    char CodePasswd[40];
    struct user_define_scada* UserDefPtr;

    BufSize = 8;
    BufPtr =  (char*)malloc(BufSize);
    retNums = GetAllRec(PUBLIC, USER_DEFINE_NO, BufPtr, BufSize);
    UserDefPtr = (user_define_scada* )BufPtr;

    for(loop = 0; loop < retNums; loop++){
        if(strcmp(WideCharToMulityByte(userName), UserDefPtr->user_name) == 0)
            break;
        UserDefPtr++;
    }

    if(loop >= retNums){
        if (BufPtr){
            free( BufPtr);
            BufPtr =NULL;
        }

        TRACE_ERROR("user name err name=%s! \n",WideCharToMulityByte(userName));
        return 0;
    }

    EncodePwd(WideCharToMulityByte(userPassword), CodePasswd);
    if(strcmp(CodePasswd, UserDefPtr->user_password) != 0)  {
        if (BufPtr){
            free( BufPtr);
            BufPtr =NULL;
        }

        TRACE_ERROR("user pwd err pwd=%s ! \n",WideCharToMulityByte(userPassword));
        return 0;
    }

    CDbMap dbmap;
    int fac_id = dbmap.GetIdxByAlias(WideCharToMulityByte(facAlias));
    if (fac_id < 0)
    {
        TRACE_ERROR("GetIdxByAlias err alias = %s \n",facAlias);
        return 0;
    }

    int node_id;
    Privilege priv ={0,0,0};
    get_node_id_by_link_id(node_id,fac_id);
    TRACE_INFO("### get_node_id_by_link_id fac_id = %d, node_id=%d \n",fac_id,node_id);
    get_user_priv(&priv,UserDefPtr->user_id,node_id);
    TRACE_INFO("### get_user_priv user_id=%d, node_id=%d, priv=%s \n",UserDefPtr->user_id,node_id,priv.priv);
    *resUserPriv = MulityByteToWideChar(priv.priv);

    return 0;
}

//server端的实现函数
int ns__GetVerifyAuthority(struct soap *para_soap, long sessionID,xsd__string turbineIP,struct ns__userAuth *resUserAuth)
{
    int ret;

    TableOp TablePtr;
    if( TablePtr.TableOpen(SCADA,SESSION_INFO_NO) < 0 )
        return -1;

    int   size = sizeof(session_info_scada);
    char* tmpstr = (char *)malloc(size);
    ret = TablePtr.TableGet((char*)&sessionID, tmpstr, sizeof(session_info_scada));
    TablePtr.TableClose();
    if( ret < 0 )
    {
        free(tmpstr);
        return -1;
    }

    struct session_info_scada *pstru;
    pstru = (session_info_scada *)tmpstr;
    struct user_define_scada pUser;

    if( pstru->logon_time > 0 && pstru->user_id > 0 )
    {
        TableOp ptmp;
        ret = ptmp.TableOpen(PUBLIC, USER_DEFINE_NO);
        if( ret < 0 )
        {
            free(tmpstr);
            TablePtr.TableClose();
            return -1;
        }

        ret = ptmp.TableGet((char *)&(pstru->user_id), (char *)&pUser, sizeof(user_define_scada));
        ptmp.TableClose();
        if( ret < 0 )
        {
            free(tmpstr);
            TablePtr.TableClose();
            return -1;
        }
    }


    char uPriv[33];
    memset(uPriv,'0',sizeof(uPriv));
    uPriv[32] = '\0';

    //scada1.0的权限
    uPriv[0] = pUser.user_privilege[PRIV_SINGLE_DISABLE_SC];
    uPriv[1] = pUser.user_privilege[PRIV_COMPONENT_CONTROL];
    uPriv[2] = pUser.user_privilege[PRIV_DIAGNOSIS_MAINTENANCE];
    uPriv[3] = pUser.user_privilege[PRIV_TURBINE_RESET_2];
    uPriv[5] = pUser.user_privilege[PRIV_TURBINE_RESET_3];
    uPriv[6] = pUser.user_privilege[PRIV_VIEW_PARAMETER];
    uPriv[7] = pUser.user_privilege[PRIV_WRITE_GENERAL_PARAMETER];
    uPriv[8] = pUser.user_privilege[PRIV_WRITE_IMPORTANT_PARAMETER];

    unsigned int _auth;
    converBinToDec(uPriv,_auth);
    resUserAuth->auth = _auth;

    sprintf(uName,"");
    memcpy(uName,pUser.user_name,32);
    resUserAuth->userName = MulityByteToWideChar(uName); 
    
    return 0;
}

//server端的实现函数
int ns__SendTurboxAlarm(struct soap *para_soap, xsd__string user,xsd__string wtgAlias,xsd__string opDesc,xsd__string *resSignal)
{
    int ret;
    CDbMap dbmap;;
    int wtgId = dbmap.GetIdxByAlias(WideCharToMulityByte(wtgAlias));
    if (wtgId == -1)
    {
        char pwstr[] ="fail";
        *resSignal = MulityByteToWideChar(pwstr);
        printf("Invalid WtgAlias:%s\n",wtgAlias);
        return 0;
    }

    char wtg_name[64]={0};
    dbmap.GetNameByIdx(wtgId,wtg_name,64);

    int counts = 1;
    char warn_app_type = 13; //Turbox告警
    int  warn_len = 250;
    char warn_buf[250]={0};

    char* content = (char*)malloc(300);
    memset(content,0,300);
    int lenth =0;
    memcpy(content+lenth,&counts,sizeof(int));
    lenth +=sizeof(int);
    memcpy(content+lenth,&warn_app_type,sizeof(char));
    lenth +=sizeof(char);
    memcpy(content+lenth,&wtgId,sizeof(int));
    lenth +=sizeof(int);
    memcpy(content+lenth,&warn_len,sizeof(int));
    lenth +=sizeof(int);


    sprintf(warn_buf,"%s %s%s",wtg_name,WideCharToMulityByte(user),WideCharToMulityByte(opDesc));
    memcpy(content+lenth,warn_buf,sizeof(warn_buf));
    lenth +=sizeof(warn_buf);

    printf("###  TurBox WARN:: buf =  %s\n",warn_buf);

    ret = msgbus_broad1.msgbus_send_message(
                            MSGBUS_REPORT_BROADCAST_SAFE,
                            MSGBUS_OTHER_APP_WARN,
                            MSGBUS_SERVER_HOST,
                            "report_process_svr",
                            content,lenth);

    if(ret < 0)
    {
        printf("[MSGBUS SEND Error]Send MSGBUS_TURBOX_OP to report_process_svr Failed! \n");
        char pwstr[] ="fail";
        *resSignal = MulityByteToWideChar(pwstr);
        return 0;
    }
    if (content)
    {
        free(content);
        content = NULL;
    }

    char pwstr[] ="success";
    *resSignal = MulityByteToWideChar(pwstr);

    return 0;
}


//server端的实现函数
int ns__SendCMSAlarm(struct soap *para_soap, xsd__string user,xsd__string wtgAlias,xsd__string opDesc,xsd__string *resSignal)
{
    int ret;
    CDbMap dbmap;;
    int wtgId = dbmap.GetIdxByAlias(WideCharToMulityByte(wtgAlias));
    if (wtgId == -1)
    {
        char pwstr[] ="fail";
        *resSignal = MulityByteToWideChar(pwstr);
        TRACE_ERROR("Invalid WtgAlias:%s\n",wtgAlias);
        return 0;
    }

    char wtg_name[64]={0};
    dbmap.GetNameByIdx(wtgId,wtg_name,64);

    int counts = 1;
    char warn_app_type = 10; //CMS告警
    int  warn_len = 250;
    char warn_buf[250]={0};

    char* content = (char*)malloc(300);
    memset(content,0,300);
    int lenth =0;
    memcpy(content+lenth,&counts,sizeof(int));
    lenth +=sizeof(int);
    memcpy(content+lenth,&warn_app_type,sizeof(char));
    lenth +=sizeof(char);
    memcpy(content+lenth,&wtgId,sizeof(int));
    lenth +=sizeof(int);
    memcpy(content+lenth,&warn_len,sizeof(int));
    lenth +=sizeof(int);

    sprintf(warn_buf,"%s %s%s",wtg_name,WideCharToMulityByte(user),WideCharToMulityByte(opDesc));
    memcpy(content+lenth,warn_buf,sizeof(warn_buf));
    lenth +=sizeof(warn_buf);

    ret = msgbus_broad1.msgbus_send_message(
        MSGBUS_REPORT_BROADCAST_SAFE,
        MSGBUS_OTHER_APP_WARN,
        MSGBUS_SERVER_HOST,
        "report_process_svr",
        content,lenth);


    printf("###  CMS WARN:: buf =  %s\n",warn_buf);

    if(ret < 0)
    {
        TRACE_FATAL("[MSGBUS SEND Error]Send CMS ALARM to report_process_svr Failed! \n");
        char pwstr[] ="fail";
        *resSignal = MulityByteToWideChar(pwstr);
        return 0;
    }
    if (content)
    {
        free(content);
        content = NULL;
    }

    char pwstr[] ="success";
    *resSignal = MulityByteToWideChar(pwstr);

    return 0;
}


//server端的实现函数
int ns__ModifyAlarmBySC(struct soap *para_soap, std::string SCName,int ShowFlag,std::string *res)
{
    //char* content = (char*)malloc(100);
    //memset(content,0,100);

    //int lenth =0;
    //memcpy(content+lenth,SCName.c_str(),64);
    //lenth +=64;
    //memcpy(content+lenth,&ShowFlag,sizeof(int));
    //lenth +=sizeof(int);

    //int ret = msgbus_broad1.msgbus_send_message(MSGBUS_REPORT_BROADCAST_SAFE,
    //                                  MSGBUS_CGN_MODIFY_AC,
    //                                  MSGBUS_SERVER_HOST,
    //                                  "webservice_svr",
    //                                  content,lenth);

    //if (content)
    //{
    //  free(content);
    //  content = NULL;
    //}

    //if(ret < 0)
    //{
    //  TRACE_FATAL("[MSGBUS SEND Error]Send MSGBUS_CGN_MODIFY_AC to webservice_svr Failed! \n");
    //  *res ="fail";
    //}
    //else
    //{
    //  *res ="success";
    //}

    return 0;
}

//server端的实现函数
int ns__ModifyMCNumBySC(struct soap *para_soap, std::string SCName,int McNum,std::string *res)
{
    char* content = (char*)malloc(100);
    memset(content,0,100);

    int lenth =0;
    memcpy(content+lenth,SCName.c_str(),64);
    lenth +=64;
    memcpy(content+lenth,&McNum,sizeof(int));
    lenth +=sizeof(int);

    int ret = msgbus_broad1.msgbus_send_message(MSGBUS_REPORT_BROADCAST_SAFE,
        MSGBUS_CGN_MODIFY_MC,
        MSGBUS_SERVER_HOST,
        "webservice_svr",
        content,lenth);

    if (content)
    {
        free(content);
        content = NULL;
    }

    if(ret < 0)
    {
        TRACE_FATAL("[MSGBUS SEND Error]Send MSGBUS_CGN_MODIFY_MC to webservice_svr Failed! \n");
        *res ="fail";
    }
    else
    {
        *res ="success";
    }

    return 0;
}



//server端实现函数
int ns__GetAreaInfoBySessionId(struct soap* para_soap, long sessionID, struct ns__areaInfo *resAreaInfo)
{
    int user_max_len =32,node_max_len =64;
    int fac_num = 0;
    QList<int> fid_list;
    fid_list.clear();

    int ret;

    TableOp TablePtr;
    if( TablePtr.TableOpen(SCADA,SESSION_INFO_NO) < 0 )
        return -1;

    int   size = sizeof(session_info_scada);
    char* tmpstr = (char *)malloc(size);
    ret = TablePtr.TableGet((char*)&sessionID, tmpstr, sizeof(session_info_scada));
    TablePtr.TableClose();
    if( ret < 0 ){
        free(tmpstr);
        return -1;
    }

    struct session_info_scada *pstru;
    pstru = (session_info_scada *)tmpstr;

    get_area_info_by_user_id(userName,user_max_len,fid_list,fac_num,pstru->user_id);

    resAreaInfo->userName = MulityByteToWideChar(userName);
    //resAreaInfo->rootNode = MulityByteToWideChar(nodeName);

    resAreaInfo->facNum = fac_num;
    QString strQ="";
    for (int i=0;i<fac_num;i++)
    {
        QString qstr =  QString::number(fid_list.at(i), 10);
        strQ += qstr;
        if (i!=fac_num-1)
            strQ += ",";        
    }
    std::string strStd= strQ.toStdString();
    listFac = new char[strStd.length()+1];
    strcpy(listFac,strStd.c_str());
    resAreaInfo->facList = MulityByteToWideChar(listFac);

    delete[] listFac;
    listFac =NULL;

    return 0;
}

int getPointValueById(int yc_id,char *sTime,char *eTime,int &ret_num,float *yc_value)
{
    int retcode = 0;
    char *result_link = NULL;
    RESULT_HEAD2 *result_head = NULL;
    FIELD_INFO *field_info = NULL;  
    char sql_statement[500];
    int data_num = 0;

    short error_no = 0;
    char* error_message = NULL;
    char *result_buffptr=NULL;
    int result_length=0;

    CHdbQuery * pQuery = m_HdbConn->get_query();
    sprintf(sql_statement,"select HISTORY_TABLE_NAME,HISTORY_COLUMN_NAME from yc_sample_define where yc_id='00'||'%d'||'009'",yc_id);
    retcode = pQuery->ExecuteQuery( sql_statement, NULL_IS_ZERO);

    result_head = pQuery->GetQueryHead();
    field_info = pQuery->GetFieldInfo();
    result_link = pQuery->GetQueryData();
    data_num = result_head->data_num;
    if(data_num <= 0)
    {
        return -1;
    }

    char hs_table[16]={0};
    char hs_column[16]={0};
    int cur_pointer=0;
    memcpy(hs_table, result_link, field_info[0].field_length);
    cur_pointer += field_info[0].field_length;
    memcpy(hs_column, result_link+cur_pointer, field_info[1].field_length);


    sprintf(sql_statement,"select %s from %s t where t.occur_time > %s and t.occur_time <= %s",
        hs_column,hs_table,sTime,eTime);
    retcode = pQuery->ExecuteQuery( sql_statement, NULL_IS_ZERO);

    result_head = pQuery->GetQueryHead();
    field_info = pQuery->GetFieldInfo();
    result_link = pQuery->GetQueryData();
    data_num = result_head->data_num;
    if(data_num < 0)
    {
        return -1;
    }

    cur_pointer = 0;
    for (int i= 0;i<data_num;i++)
    {
        memcpy((char*)&yc_value[i], result_link+cur_pointer, field_info[0].field_length);
        cur_pointer += field_info[0].field_length;
    }

    ret_num = data_num;
    return 1;

}


//server端实现函数
int ns__GetPointValue10m(struct soap*, wchar_t *wtg_id, wchar_t *pointname, wchar_t *timestamp, struct ns__pointValue *resvalue)
{
    int data_num = 0;
    int ret = 0;
    char code[8] = {0};
    char msg[1000]={0};
    int year,mon,day,hour,min,sec;
    char *inDateTime = WideCharToMulityByte(timestamp);
    sscanf(inDateTime,"%4d-%2d-%2d %2d:%2d:%2d",&year,&mon,&day,&hour,&min,&sec);

    if (0 >= (int) (mon -= 2))
    { 
        mon += 12; 
        year -= 1;
    }
    unsigned long gmt_t;
    gmt_t = (((
        (unsigned long) (year/4 - year/100 + year/400 + 367*mon/12 + day) +
        year*365 - 719499
        )*24 + hour 
        )*60 + min 
        )*60 + sec;

    CDbMap dbmap;
    MultiTimeZone multTz;
    char sTime[100],eTime[100];
    char wtg_alias[32]={0};
    char *wtgId = WideCharToMulityByte(wtg_id);
    char tzname[32];
    strcpy(tzname,"");
    int wtg_id_i = atoi(wtgId);
    multTz.GetTimeZoneByIdx(wtg_id_i, tzname);
    multTz.time_t_to_date_string((time_t)gmt_t-600,sTime,tzname);
    multTz.time_t_to_date_string((time_t)gmt_t,eTime,tzname);

    wtg_id_i = atoi(wtgId);
    ret = dbmap.GetAliasByIdx(wtg_id_i,wtg_alias,sizeof(wtg_alias));

    char yc_alias[64]={0};
    char *pointName = WideCharToMulityByte(pointname);
    sprintf(yc_alias,"%s.%s",wtg_alias,pointName);

    TRACE_INFO("Info: %d  %s %s  %s\n",wtg_id_i,yc_alias,sTime,eTime);
    delete[] pointName;
    delete[] inDateTime;
    delete[] wtgId;

    int ycyx_id = dbmap.GetIdxByAlias(yc_alias);
    if (ycyx_id<0){
        strcpy(code,"20000");
        strcpy(msg,"get yc_id from yc_alias error!");
        resvalue->code = MulityByteToWideChar(code);
        resvalue->message = MulityByteToWideChar(msg);
        TRACE_ERROR("GetIdxByAlias error: yc_alias:%s ycyx_id: %d\n",yc_alias,ycyx_id);
        delete[] wtg_id;
        delete[] pointname;
        delete[] timestamp;
        return 0;
    }

    float avg = 0;
    float std = 0;
    if (ycyx_id/1000000==61)
    {
        unsigned char cval;
        dbmap.GetYxValueByIdx(ycyx_id,&cval);
        avg = (float)cval;
        std = -1;
    }
    else
    {
        float pointvalue[10];
        ret = getPointValueById(ycyx_id,sTime,eTime,data_num,pointvalue);
        if (ret<0)
        {
            strcpy(code,"20000");
            strcpy(msg,"cannot get records from yc_hs!");
            resvalue->code = MulityByteToWideChar(code);
            resvalue->message = MulityByteToWideChar(msg);
            TRACE_ERROR("getPointValueById error: ycyx_id: %d\n",ycyx_id);
            delete[] wtg_id;
            delete[] pointname;
            delete[] timestamp;
            return 0;
        }

        float sum = 0;
        float tmp = 0;
        for (int i=0;i<data_num;i++)
        {
            sum += pointvalue[i];
        }
        if (data_num>0)
        {
            avg = sum/data_num;
        }
        

        for (int i=0;i<data_num;i++)
        {
            tmp += pow((pointvalue[i]-avg),2);
        }
        if (data_num>0)
        {
            std = sqrt(tmp/data_num);
        }
    }



    resvalue->value = avg;
    resvalue->std = std;
    strcpy(code,"10000");
    strcpy(msg,"");
    resvalue->code = MulityByteToWideChar(code);
    resvalue->message = MulityByteToWideChar(msg);
    delete[] wtg_id;
    delete[] pointname;
    delete[] timestamp;
    return 0;
}